package com.dx.mes.service.special.service;


import static com.dx.mes.common.bean.def.GenericDef.ABN_ACTION_HOLD;
import static com.dx.mes.common.bean.def.GenericDef.EVT_HOLD_CST;
import static com.dx.mes.common.bean.def.GenericDef.EVT_HOLD_RELEASE;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPBOXHLD_BOX_ID_EMPTY;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPBOXHLD_HOLD_RLSE_SORT;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPBOXHLD_INVALID_INPUT;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPBOXHLD_PRD_NOT_EXIST;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPBOXHLD_STATUS_INVALID;
import static com.dx.mes.common.bean.def.GenericDef.E_FSPGRDCHG_STATUS_MISMATCH;
import static com.dx.mes.common.bean.def.GenericDef.PROC_HOLD;
import static com.dx.mes.common.bean.def.GenericDef.PROC_WAIT;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_OK;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.dx.mes.common.bean.def.GenericDef.RETURN_MESG_OK;
import static com.dx.mes.common.bean.def.GenericDef.TRX_OUT;
import static com.dx.mes.common.bean.def.GenericDef.T_FSPBOXHLD;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dx.common.table.ppt.Ret_prd_abn;
import com.dx.common.table.ppt.Ret_prd_abnId;
import com.dx.common.table.ppt.Ret_prd_info;
import com.dx.mes.common.dao.IRetBoxDao;
import com.dx.mes.common.dao.IRetPrdAbnDao;
import com.dx.mes.common.dao.IRetPrdInfoDao;
import com.dx.mes.common.dao.IRetPrdOutDao;
import com.dx.mes.common.transcoder.util.AppContext;
import com.dx.mes.common.transcoder.util.GUIDGenerator;
import com.dx.mes.common.transcoder.util.JacksonUtil;
import com.dx.mes.common.transcoder.util.LogUtils;
import com.dx.mes.common.transcoder.util.Util;
import com.dx.mes.facade.special.service.IFspboxholdService;
import com.dx.mes.facade.special.tx.Fspboxhold.FspboxholdI;
import com.dx.mes.facade.special.tx.Fspboxhold.FspboxholdIA;
import com.dx.mes.facade.special.tx.Fspboxhold.FspboxholdO;
import com.dx.mes.facade.special.tx.Fspboxhold.FspboxholdOA;

@Service("fspboxholdService")
public class FspboxholdService implements IFspboxholdService {
	private LogUtils logUtils;
	private static String TX_NAME = T_FSPBOXHLD;

	@Autowired
	private IRetBoxDao retBoxDao;
	@Autowired
	private IRetPrdInfoDao retPrdInfoDao;
	@Autowired
	private IRetPrdAbnDao retPrdAbnDao;
	@Autowired
	private IRetPrdOutDao retPrdOutDao;

	public String subMainProc(String evt_no, String strInMsg) {
		AppContext.clear();
		AppContext.setCurrServiceName(FspboxholdService.class.getSimpleName());
		AppContext.setCurrEventNumber(evt_no);
		logUtils = new LogUtils(FspboxholdService.class);
		logUtils.info("[InTrx:" + strInMsg + "]");
//		Session session = retPrdInfoDao.getCrSession();

		String outMsg = "";
		FspboxholdI inTrx = new FspboxholdI();
		FspboxholdO outTrx = new FspboxholdO();

		outTrx.setTrx_id(TX_NAME);
		outTrx.setType_id(TRX_OUT);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));

		try {
			inTrx = JacksonUtil.fromJson(strInMsg, FspboxholdI.class);

			subMainProc2(inTrx.getAction_flg().toCharArray()[0], inTrx, outTrx);
			if (!outTrx.getRtn_code().equals(RETURN_CODE_OK)) {
				TransactionAspectSupport.currentTransactionStatus()
						.setRollbackOnly();
			} else {
				retPrdInfoDao.flushCurSession();
			}
		} catch (Exception ex) {
			outTrx.setRtn_mesg(ex.toString());
			outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
			logUtils.error(Util.stackTraceToString(ex));
			TransactionAspectSupport.currentTransactionStatus()
					.setRollbackOnly();
		} finally {
			outMsg = JacksonUtil.toJSONStr(outTrx);
			logUtils.info("[OutTrx:" + outTrx + "]");
		}
		return outMsg;
	}

	private void subMainProc2(char actionType, FspboxholdI inTrx, FspboxholdO outTrx) {

		switch (actionType) {
			case 'Q': {
				queryHoldSeqFunc(inTrx, outTrx);
				break;
			}
			case 'H': {
				holdseq(inTrx, outTrx);//保留
				break;
			}
			case 'M': {
				moveseq(inTrx, outTrx);//释放
				break;
			}

			default: {
				String gszMsgBuf = "Invalide type input: [" + actionType + "]";
				outTrx.setRtn_code(String.valueOf(E_FSPBOXHLD_INVALID_INPUT));
				outTrx.setRtn_mesg(gszMsgBuf);
				return;
			}
		}
	}

	private void queryHoldSeqFunc(FspboxholdI inTrx, FspboxholdO outTrx) {

		String prd_seq_id = inTrx.getPrd_seq_id();
		String woId = inTrx.getWo_id();
		String opeId = inTrx.getOpe_id();
		String sql = "select distinct evt_seq_id_fk from ret_prd_abn where act_code='HOLD'";
		if (!Util.isSpaceCheck(prd_seq_id)) {
			sql=sql+" and prd_seq_id_fk = '" + prd_seq_id + "'";
		}
		if (!Util.isSpaceCheck(opeId)) {
			sql=sql+" and nx_ope_id_fk = '" + opeId + "'";
		}
		if (!Util.isSpaceCheck(woId)) {
			sql=sql+" and  wo_id_fk = '" + woId + "'";
		}
		List<String> seqList = retPrdAbnDao.findBySQL(sql);
		List<FspboxholdOA> oaryList = new ArrayList<FspboxholdOA>();
		for (String evt_seq_id : seqList) {
			String hq = "select * from ret_prd_abn where evt_seq_id_fk = '" + evt_seq_id + "'";
			List<Ret_prd_abn> ret_prd_abn = retPrdAbnDao.findBySQL(hq, Ret_prd_abn.class);
			FspboxholdOA oary = new FspboxholdOA();
			oary.setEvt_seq_id_fk(evt_seq_id);
			oary.setPrd_seq_id(ret_prd_abn.get(0).getId().getPrd_seq_id_fk());
			oary.setRsn_cate(ret_prd_abn.get(0).getRsn_cate());
			oary.setRsn_dept(ret_prd_abn.get(0).getRsn_dept());
			oary.setRsn_code(ret_prd_abn.get(0).getRsn_code());
			oary.setEvt_usr(ret_prd_abn.get(0).getEvt_usr());
			oary.setEvt_timestamp(ret_prd_abn.get(0).getEvt_timestamp().toString());
			oaryList.add(oary);
		}

		outTrx.setTbl_cnt(oaryList.size());
		outTrx.setOary(oaryList);
		outTrx.setRtn_code(RETURN_CODE_OK);
		outTrx.setRtn_mesg(RETURN_MESG_OK);
	}

	private void holdseq(FspboxholdI inTrx,FspboxholdO outTrx){
		Timestamp evt_timestamp = Util.getCurrentTimestamp();
		String rsn_cate = inTrx.getRsn_cate();//原因种类
		String rsn_code = inTrx.getRsn_code();//原因代码
		String rsn_dept = inTrx.getRsn_dept();//原因部门

		List<Ret_prd_info>  ret_prd_infoM = new ArrayList<Ret_prd_info>();
		List<Ret_prd_abn>   ret_prd_abnN  = new ArrayList<Ret_prd_abn>();
		for (FspboxholdIA iaryA:inTrx.getIary()) {
			Ret_prd_info ret_prd_info = retPrdInfoDao.get(iaryA.getPrd_seq_id());
			if(null == ret_prd_info){
				outTrx.setRtn_code(E_FSPBOXHLD_PRD_NOT_EXIST+"");
				outTrx.setRtn_mesg("玻璃["+iaryA.getPrd_seq_id()+"]不存在!");
				return;
			}

			if(!PROC_WAIT.equals(ret_prd_info.getPrd_stat())){
				outTrx.setRtn_code(E_FSPGRDCHG_STATUS_MISMATCH+"");
				outTrx.setRtn_mesg("玻璃["+iaryA.getPrd_seq_id()+"]状态["+ret_prd_info.getPrd_stat()+"]不正确!必须是[" + PROC_WAIT + "]");
				return;
			}
			//给HOLD的玻璃，添加对应的HOLD原因及部门代码
			ret_prd_info.setRsn_cate(rsn_cate);
			ret_prd_info.setRsn_code(rsn_code);
			ret_prd_info.setRsn_dept(rsn_dept);
			ret_prd_info.setPv_prd_stat_fk(ret_prd_info.getPrd_stat());
			ret_prd_info.setPrd_stat(PROC_HOLD);
			ret_prd_info.setEvt_usr(inTrx.getEvt_user());
			ret_prd_info.setEvt_timestamp(evt_timestamp);
			ret_prd_info.setEvt_cate(EVT_HOLD_CST);
			ret_prd_infoM.add(ret_prd_info);


			String evt_seq_id = GUIDGenerator.javaGUID();
			Ret_prd_abn ret_prd_abn = new Ret_prd_abn();
			Ret_prd_abnId ret_prd_abnId = new Ret_prd_abnId();
			ret_prd_abnId.setPrd_seq_id_fk(ret_prd_info.getPrd_seq_id());
			ret_prd_abnId.setEvt_seq_id_fk(evt_seq_id);
			ret_prd_abn.setId(ret_prd_abnId);
			ret_prd_abn.setWo_id_fk(ret_prd_info.getWo_id_fk());
			ret_prd_abn.setNx_ope_id_fk(ret_prd_info.getNx_ope_id_fk());
			ret_prd_abn.setBox_id_fk(ret_prd_info.getBox_id_fk());
			ret_prd_abn.setAct_code(ABN_ACTION_HOLD);
			ret_prd_abn.setPrd_stat(PROC_HOLD);
			ret_prd_abn.setRsn_dept(rsn_dept);
			ret_prd_abn.setRsn_cate(rsn_cate);
			ret_prd_abn.setRsn_code(rsn_code);

			ret_prd_abn.setPv_prd_stat(ret_prd_info.getPv_prd_stat_fk());
			ret_prd_abn.setEvt_usr(inTrx.getEvt_user());
			ret_prd_abn.setEvt_timestamp(evt_timestamp);
			ret_prd_abnN.add(ret_prd_abn);
		}
		retPrdInfoDao.saveOrUpdateAll(ret_prd_infoM);
		retPrdAbnDao.saveOrUpdateAll(ret_prd_abnN);
		outTrx.setRtn_code(RETURN_CODE_OK);
		outTrx.setRtn_mesg(RETURN_MESG_OK);
	}

	private void moveseq(FspboxholdI inTrx, FspboxholdO outTrx) {
		String prd_seq_id= inTrx.getPrd_seq_id();
		String evt_user = inTrx.getEvt_user();
		String rsn_cate = inTrx.getRsn_cate();//原因种类
		String rsn_code = inTrx.getRsn_code();//原因代码
		String rsn_dept = inTrx.getRsn_dept();//原因部门
		String evt_seq_id_fk = inTrx.getEvt_seq_id_fk();
		Timestamp evt_timestamp = Util.getCurrentTimestamp();
		if (Util.isSpaceCheck(prd_seq_id)){
			outTrx.setRtn_code(E_FSPBOXHLD_BOX_ID_EMPTY+"");
			outTrx.setRtn_mesg("请选择需要取消保留的玻璃代码");
			return;
		}
		
		Ret_prd_info ret_prd_info = retPrdInfoDao.get(prd_seq_id);
		if(null == ret_prd_info){
			outTrx.setRtn_code(E_FSPBOXHLD_PRD_NOT_EXIST+"");
			outTrx.setRtn_mesg("玻璃["+prd_seq_id+"]不存在!");
			return;
		}
		
		if (PROC_HOLD.equalsIgnoreCase(ret_prd_info.getPrd_stat())) {
				//from abn
				String sql = "select * from ret_prd_abn where prd_seq_id_fk = '"+ prd_seq_id +"' and act_code = '"
						+ PROC_HOLD + "' order by evt_timestamp desc";
				List<Ret_prd_abn> ret_prd_abns = retPrdAbnDao.findBySQL(sql, Ret_prd_abn.class);
				String evt_usr = ret_prd_abns.get(0).getEvt_usr();
				if (!inTrx.getEvt_user().equals(evt_usr)) {
					outTrx.setRtn_code(E_FSPBOXHLD_HOLD_RLSE_SORT+"");
					outTrx.setRtn_mesg("此玻璃最后操作人是["+ret_prd_abns.get(0).getEvt_usr()+"],请该用户先进行释放！");
					return;
				}
				if(!evt_seq_id_fk.equals(ret_prd_abns.get(0).getId().getEvt_seq_id_fk())){
					outTrx.setRtn_code(E_FSPBOXHLD_HOLD_RLSE_SORT+"");
					outTrx.setRtn_mesg("此玻璃最后操作时间是["+ret_prd_abns.get(0).getEvt_timestamp()+"],请该用户按照时间先后顺序进行释放！");
					return;
				}
				
				if (StringUtils.isNotBlank(ret_prd_info.getPrd_stat())) {
					ret_prd_info.setPv_prd_stat_fk(ret_prd_info.getPrd_stat());
				}
				ret_prd_info.setPrd_stat(ret_prd_abns.get(0).getPv_prd_stat());
				ret_prd_info.setRsn_cate(rsn_cate);
				ret_prd_info.setRsn_code(rsn_code);
				ret_prd_info.setRsn_dept(rsn_dept);
				ret_prd_info.setEvt_usr(evt_user);
				ret_prd_info.setEvt_timestamp(evt_timestamp);
				ret_prd_info.setEvt_cate(EVT_HOLD_RELEASE);
				retPrdInfoDao.update(ret_prd_info);
				
				//删除abn
				String hql = "delete from ret_prd_abn where evt_seq_id_fk = '"+evt_seq_id_fk+"' and prd_seq_id_fk = '"+prd_seq_id+"'";
			    retPrdAbnDao.getCrSession().createSQLQuery(hql).executeUpdate();
			} else {
				outTrx.setRtn_code(E_FSPBOXHLD_STATUS_INVALID+"");
				outTrx.setRtn_mesg("玻璃状态为["+ ret_prd_info.getPrd_stat() +"]不正确,必须是[" + PROC_HOLD + "]状态!");
				return;
		}
 		outTrx.setRtn_code(RETURN_CODE_OK);
		outTrx.setRtn_mesg(RETURN_MESG_OK);
	}

}
